#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <string.h>
#include <stdlib.h>

#define NETLINK_TEST 25							//自定义netlink号
#define DATA_BUF 256							//发送与接收数据buf大小

int main(int argc, char **argv){
	int fd;
	struct sockaddr_nl srcaddr, dstaddr;
	struct nlmsghdr *nlh;
	char *data = "am user data";
	struct iovec iov;
	struct msghdr msg;

	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_TEST);		//创建NETLINK socket
	if(fd < 0){
		perror("socket()");
		return -1;
	}

	memset(&srcaddr, 0x0, sizeof(struct sockaddr_nl));
	memset(&dstaddr, 0x0, sizeof(struct sockaddr_nl));
	srcaddr.nl_family = AF_NETLINK;					//源地址，设置netlink族
	srcaddr.nl_pid = getpid();					//通知内核，应用层的port id
	srcaddr.nl_groups = 0;						//禁止组播
	dstaddr.nl_family = AF_NETLINK;					//目的地址，设置netlink族
	dstaddr.nl_pid = 0;						//设置目的地址portid，0为发送至内核
	dstaddr.nl_groups = 0;						//禁止组播
	bind(fd, (struct sockaddr *)&srcaddr, sizeof(struct sockaddr_nl));
	
	nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(DATA_BUF));
	memset(nlh, 0x0, sizeof(NLMSG_SPACE(DATA_BUF)));
	nlh->nlmsg_len = NLMSG_SPACE(DATA_BUF);
	nlh->nlmsg_type = 0;
	nlh->nlmsg_flags = 0;//TODO  NLM_F_REQUEST 
	nlh->nlmsg_pid = getpid();					//消息头设置portid
	memcpy(NLMSG_DATA(nlh), data, strlen(data));

	iov.iov_base = (void *)nlh;
	iov.iov_len = nlh->nlmsg_len;

	memset(&msg, 0x0, sizeof(struct msghdr));
	msg.msg_name = (void *)&dstaddr;
	msg.msg_namelen = sizeof(struct sockaddr_nl);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	sendmsg(fd, &msg, 0);						//发送消息
	printf("send msg: %s\n", data);

	int recvlen;
	char *recvdata;
	
	memset(nlh, 0x0, NLMSG_SPACE(DATA_BUF));
	recvlen = recvmsg(fd, &msg, 0);					//接收消息
	recvdata = NLMSG_DATA(nlh);
	if(recvdata)
		printf("recv msg: %s\n", recvdata);
	else
		printf("recv null\n");

	return 0;
}
